home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS in a Box 7
/
BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso
/
Files
/
Tele
/
C
/
Comet2.1.3.cpt
/
Comet
/
main.c
< prev
next >
Wrap
Text File
|
1991-10-22
|
39KB
|
1,824 lines
/*
Copyright Cornell University 1986. All rights are reserved.
*/
/***************************************************************************
** 3270 Driver initializations, main program, & error handler **
****************************************************************************
** Developed at Cornell University by: **
** Richard Cogger, Peter Hoyt, Kevin Saunders, & John Lynn **
** includes calls to TCP, IP, and tasking routines developed at MIT **
***************************************************************************/
/* tn3270.c contains the main() loop and various support routines */
#ifdef MULTI
/* multiple windows version */
#include <em.h>
#include <cntl.h>
#include <key.h>
#include <macdefs.h>
#include <h19.h>
#include <timer.h>
#include <ft.h>
#include <3270.h> /* external variables & constants */
#include <cntldefs.h>
#include <resdefs.h>
#include "xlate.h"
#include "menudefs.h"
#include "tftp.h"
#ifdef DUALTCP
#include <net.h> /* NEW merged TCP drags in task.h */
#else
#include <net.h> /* NEW merged TCP drags in task.h */
#include <q.h> /* TODO should be different with MACTCP alone */
extern char timertripped; /* the timer requires service */
#endif
#else
#ifdef MACTCP
#include <q.h>
#else
#include <tcp.h>
#endif
#include <stdio.h>
#include <osutil.h>
#include <quickdraw.h>
#include <resource.h>
#include <toolutil.h>
#include <window.h>
#include <control.h>
#include <font.h>
#include <event.h>
#include <desk.h>
#include <packages.h>
#include <segment.h>
#include <menu.h>
#include <dialog.h>
#include <memory.h>
#include <cntl.h>
#include <key.h>
#include <macdefs.h>
#include <h19.h>
#include <timer.h>
#include <emdefs.h>
#include <telnet.h>
#include <ft.h>
#include <3270.h> /* external variables & constants */
#include <cntldefs.h>
#include <resdefs.h>
#include "xlate.h"
#include "menudefs.h"
#include "tftp.h"
#endif
#ifdef DUALTCP
#undef MACTCP
/* make both tcps in one package */
#endif
struct winds * conns[MAXWIND];
short conncount;
/* true globals */
#ifdef MULTI
struct winds * emdp; /* pointer to connection block we're using */
struct winds * keydp; /* pointer to top window connection block we're using */
#endif
short mfbackonly; /* run whole app only in background */
WindowPtr keywindow; /* the active window, emwindow or textwindow */
WindowPtr iconwindow; /* top go-away window, shows tn3270 icon */
WindowPtr emwindow; /* the current output emulator window */
#ifdef USEHELPWINDOW
/* help window vars */
WindowPtr helpwindow; /* there is one help window */
struct windtext helptext;
struct windtext {
TEHandle texthand; /* with a TextEdit box and a scrollbar */
int FirstLine; /* the number of the line at the top */
short textscrapped; /* the TE scrap has been touched and must be coerced */
short textlines; /* # of lines in page */
ControlHandle scrollhand; /* scroll bar control */
}
#endif
EventRecord myEvent;
short courierprint; /* print using Courier on LaserWriters? */
short appresfid; /* application resource file descriptor */
short appvol; /* application home volume */
long appdir; /* application home directory */
short appvref; /* application volume ref num */
char * setfile = "\PComet Default"; /* system folder settings default filename */
short quitonclose; /* user wants app to close when no windows */
/* connection management */
short connavailable; /* an empty connection struct is lying about */
/* TCP vars */
short cutcpopen; /* Cornell TCP has been opened */
short macipopen; /* macTCP has been opened */
short mactcpopen; /* macTCP has been opened */
short mtevent; /* MacTCP--new data or control info has arrived */
short mtcpsendasync; /* use async send w/ MacTCP */
short tftpopen; /* has tftp been initialized? */
short tftpserve; /* act as a tftp server */
short tftpask; /* query user about transfers */
short trydsdraw; /* *try* to use direct to screen drawing */
short riskydsdraw; /* only use dsdraw in FrontWindow() */
PicHandle shrinkpict; /* picture for shrink control */
PicHandle tapepict; /* picture of cassette tape */
short icon_up; /* iconwindow is up for top window */
long long1; /* useful storage for assembly routines */
long long2;
long long3;
long long4;
TEHandle helptehand;
WindowPtr helpwind;
long filltimeout;
/* mouserect sizing and tracking of cursor */
short trackon; /* flag for cursor tracking on */
Rect mouserect; /* also used by h19curset to find the targeted x,y */
short inemulator; /* an emulator is in use */
short clickdelay = 10; /* # of ticks to wait before setting a selection */
/* Cursors */
Rect cursrect; /* inviolable cursor Rect */
short curson; /* cursor state on or off */
Cursor blank = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8, 8 };
Cursor * thecursor = ␣
Rect zaprect; /* for ShieldCursor */
SysPtr paramptr; /* pointer to parameters for cursor blink time */
unsigned long cursalarm; /* tick count at which to change cursor */
RgnHandle emclip; /* holds previous em clip rect */
RgnHandle q3clip; /* for calculating new clip w/o q3 box */
/* q3 control globals */
short q3conth; /* height of quadrant 3 control button */
short q3contskip; /* size of skip every 3 buttons */
Rect boxrect; /* box in which the q3 button labels are drawn */
/* character images for direct to screen drawing */
FONTS font; /* normal font */
FONTS invfont; /* inverted */
FONTS boldfont; /* bold font */
FONTS invboldfont; /* inverted */
FONTS bvtfont; /* vt font */
FONTS invbvtfont; /* inverted */
short * chofftab9; /* array of character offsets to avoid multiplies */
short * chofftab12; /* array of character offsets to avoid multiplies */
RgnHandle updateRgn; /* rgn for scroll update regions */
short bkrd_act = 1; /* is tcp running in background mode? */
Rect dragrect; /* the drag rectangle for all windows */
/* we use a bit array to mark dirty lines a` la zapchar, here are the masks */
unsigned long modmask[32] = {
0x00000001L,
0x00000002L,
0x00000004L,
0x00000008L,
0x00000010L,
0x00000020L,
0x00000040L,
0x00000080L,
0x00000100L,
0x00000200L,
0x00000400L,
0x00000800L,
0x00001000L,
0x00002000L,
0x00004000L,
0x00008000L,
0x00010000L,
0x00020000L,
0x00040000L,
0x00080000L,
0x00100000L,
0x00200000L,
0x00400000L,
0x00800000L,
0x01000000L,
0x02000000L,
0x04000000L,
0x08000000L,
0x10000000L,
0x20000000L,
0x40000000L,
0x80000000L
};
char zapuline; /* flag to zapchar to underline character */
char zapinvert; /* flag to zapchar to underline character */
char inselection; /* flag that we are in selection range */
char skiparr[NOCHARS]; /* chars which are blank & can be skipped */
char allskiparr[NOCHARS]; /* alternate all-TRUE skiparr */
short keyboard = PLUSKEYBOARD; /* keyboard type */
short keypadswitch; /* switch SE keypad */
/* a default ibmcolormap */
struct ibmcolormap ibmcolormap = {
/* unprotected ... */
0, 0, 0, 65535, 65535, 65535, /* normal (black on white) */
50000, 1000, 1000, 65535, 65535, 65535, /* sense (red on white) */
0, 0, 0, 65535, 65535, 65535, /* intense (black on white) */
0, 0, 0, 65535, 65535, 65535, /* invis (black on white) */
/* protected ... */
0, 0, 0, 65535, 65535, 65535, /* normal (black on white) */
50000, 1000, 1000, 65535, 65535, 65535, /* sense (red on white) */
0, 0, 0, 65535, 65535, 65535, /* intense (black on white) */
0, 0, 0, 65535, 65535, 65535 /* invis (black on white) */
};
struct ibmcolormap asccolormap = {
0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, /* normal (black on white) */
0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, /* reverse (white on black) */
0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, /* bold (red on white) */
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, /* bold reverse (white on red) */
/* blink ... */
0x0000, 0x0000, 0x0000, 0xFF70, 0xFFFF, 0x3752, /* black on yellow */
0xFF70, 0xFFFF, 0x3752, 0x0000, 0x0000, 0x0000, /* rev: Yellow on black */
0xFFFF, 0x0000, 0x0000, 0xFF70, 0xFFFF, 0x3752, /* bold: red on yellow */
0xFF70, 0xFFFF, 0x3752, 0xFFFF, 0x0000, 0x0000, /* boldrev: yellow on red */
};
/* TODO ideally the strings and actions associated with the 3rd quadrant buttons
would be reconfigurable on a per-window basis... */
char * q3strings[] = {
"PF1",
"PF2",
"PF3",
"PF4",
"PF5",
"PF6",
"PF7",
"PF8",
"PF9",
"PF10",
"PF11",
"PF12",
"PF13",
"PF14",
"PF15",
"PF16",
"PF17",
"PF18",
"PF19",
"PF20",
"PF21",
"PF22",
"PF23",
"PF24",
/* VT52/VT100 labels */
"KP 1",
"KP 2",
"KP 3",
"KP 4",
"KP 5",
"KP 6",
"KP 7",
"KP 8",
"KP 9",
"KP 0",
"KP -",
"KP , (+)",
"PF1 (Gold)",
"PF2 (Help)",
"PF3",
"PF4",
"KP .",
"KP Enter",
"Find",
"Insert Here",
"Remove",
"Select",
"Prev Screen",
"Next Screen"
};
/* for ASCII vt100 mode */
char q3vtcontrols[] = {
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'p',
'm',
'l',
'P',
'Q',
'R',
'S',
'n',
'M',
'1',
'2',
'3',
'4',
'5',
'6'
};
/* for ASCII mode */
char q3controls[] = {
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'[',
'P',
'Q',
'R'
};
char * nosessionstr = "Session closed";
char * hostwait = "Connecting to host...";
char * badaddress = "Invalid host address";
/* BIGG preserve as globals for better speed */
/* shared BIGG */
/* used by dsdraw zap.asm routines */
FONTS *thefont; /* BIGG */
short xpos, ypos; /* BIGG current x, y position */
unsigned long modflg; /* BIGG line modified bit array */
unsigned long clrflg; /* BIGG line cleared bit array */
short fontwidth; /* BIGG width of font */
short ** startarr; /* BIGG dsdraw -> array of ptrs to scanline starts */
short screenbytes; /* BIGG width of screen in bytes */
short screenrem; /* BIGG screenbytes - std screen */
char * skiptest; /* current skip array to use in zap */
/* h19 BIGG */
short mode; /* BIGG interpretation mode of emulator */
unsigned char * charp; /* BIGG cursor loc for these arrays */
short inserton; /* BIGG insert mode */
short linelength; /* BIGG width of row */
short lastcol; /* BIGG linelength - 1 */
unsigned char attrib; /* BIGG normal/reverse mode for copy drawing */
short wrap_around; /* BIGG wrap at end of line if true */
/* vt100 BIGG */
short vtmode; /* BIGG new mode holder for vt100 */
unsigned short * argp; /* BIGG -> current argument */
/* 3270 BIGG */
short cmdstate; /* BIGG state of the emulator */
unsigned char *scr_map; /* BIGG screen map */
unsigned char *smap_end; /* BIGG end of map */
unsigned char *current_attr; /* BIGG pointer to most recent attribute */
unsigned char *cursor_ptr; /* BIGG current cursor position in screen map */
unsigned char * firstp; /* BIGG ptr to first data byte processed for set_map */
/* end BIGG vars */
#ifdef MACTCP
unsigned NDEBUG = TRUE; /* stupid debug flag */
struct net thisnet;
struct net * rnet;
short nnrup; /* network not responding dialog up */
struct task * tk_cur; /* subs for current task ptr */
short iplog;
extern int tcpwr_usr(); /* these are now stubs for compatibility */
extern int tcpmst_run();
extern int tcpopn_usr();
extern int tcpcls_usr();
extern int tcptmo_usr();
extern int tcppr_dot();
extern int tcpbfr();
#else
extern int tcpwr_usr();
extern int tcpmst_run();
extern int tcpopn_usr();
extern int tcpcls_usr();
extern int tcptmo_usr();
extern int tcppr_dot();
extern int tcpbfr();
#endif
unsigned long tickserial; /* next tick count to service serial port */
short serialwait; /* how long the serial mgr thinks we should wait */
unsigned long tickcursor; /* next tick count to service cursor */
unsigned long tickstats; /* next tick count to display packet counters */
extern short modaldialog;
int proc_token();
int nullputchar();
int nullputflush();
short edresetselect; /* reset selection after emulator edit action */
char isdiacritic[NOCHARS]; /* marks 0-width diacritical characters for screen drawing */
/* NEW CU TCP/ MacTCP merge features */
struct winds * tcpemdp; /* the window context in which CU tcp runs */
#ifdef KEEPALIVE
timer *tel_ayt;
#define AYTT 500 /* seconds between ayt tickles */
extern int beep_ayt();
#endif
main()
{
#ifdef MACTCP
rnet = &thisnet;
#else
#asm
public _appstak
move.l a6,_appstak ; /* set the stack bottom ptr to copy the whole stack */
#endasm
#endif
A5init(); /* save a5 */
macinit((long) (75L * 1024L));
setupapplemenu(); /* so we can chk for multifinder */
if (chkmultifinder()) {
EventRecord myEvent;
/* eventavail will put these back on the queue, but not just any event! */
EventAvail(keyDownMask, &myEvent);
EventAvail(keyDownMask, &myEvent);
EventAvail(keyDownMask, &myEvent);
/* these calls will prompt the MultiFinder to display our startup screen */
}
if (!scrinit()) {
error("Can't initialize screen");
cu_exit(-1);
}
tn_init();
ibm_init();
setupmenu();
SetEventMask(everyEvent);
/* fix event mask for autokeycommand--may cause full event queue! */
#ifdef DOHYC
hyc_init();
#endif
/* and some optional stuff */
#ifdef KEEPALIVE
if ((tel_ayt = tm_alloc()) == NULL) {
error("Unable to allocate telnet ayt timer");
cu_exit(-1);
}
tm_set(AYTT, beep_ayt, NULL, tel_ayt);
#endif
#ifdef MACTCP
tk_cur = 2L; /* needs to be nonzero so tk_yield will be called */
tm_init();
#else
/* initialize tasking */
tk_init(10000); /* size of the main task's stack */
tm_init();
#endif
/* open document files & do configuration */
openlaunchres();
fillwindclose();
/* close the copyright window if it's up */
#ifdef TFTPSERVE
/* start the tftp server and turn it on if configured on */
if (tftpserve == TFYES) {
tfs_on();
}
#endif
/* and now we run ... */
while (TRUE) {
user_act(); /* user input--process mac events */
token_service(); /* user output--handle actions waiting on the queue */
io_service(); /* for merged MacTCP/CUTCP */
screen_service(); /* update screen */
#ifdef DUALTCP
tk_yield(); /* task yield for Cornell TCP */
#else
if (timertripped)
tm_main(); /* service timer */
#endif
}
/* not reached */
cu_exit(0);
}
/* some trivial subroutines that interact with lower level code */
#ifdef KEEPALIVE
/* set a flag when timer pops (should just send an AYT!) */
beep_ayt()
{
emdp->event_reg |= TICKLE;
}
#endif
/* figure out a neat telnet socket */
tn_sock()
{
long temp;
GetDateTime(&temp);
temp &= 0xffff;
if (temp < 1000)
temp += 1000;
return((unsigned) temp);
}
/* called when a connection is opened to perform UI tasks */
opn_usr()
{
emdp->connopen = TRUE;
emdp->hycconnwait = FALSE;
if (emdp->emwindow != NULL) {
/* update the menus; first the window menu mark */
if (emdp->conntype == CONN_MACTCP || emdp->conntype == CONN_CUTCP) {
windmenumark(emdp, 0xA5); /* set a • mark */
}
else if (emdp->conntype == CONN_SERD) {
windmenumark(emdp, emdp->usebport ? '-' : '+');
/* set a mark on the menu item + for modem port,
- for printer port */
}
else if (emdp->conntype == CONN_COMMMGR) {
windmenumark(emdp, 0xA5); /* set a • mark */
}
if (keydp == NULL || emwindow == keydp->emwindow) {
if (setmsession(emdp) || setmenuconn(emdp))
DrawMenuBar();
}
restore25(); /* allow controls to be drawn */
}
}
/* called when a session is closed, window menu mark already set */
/* WARNING: twp may disappear, emdp may change! */
cls_usr()
{
if (!emdp->connopen)
return;
if (emdp->hycactive)
emdp->hycconnwait = FALSE;
emdp->connopen = FALSE;
emdp->termset = FALSE; /* no terminal type selected */
emdp->event_reg = 0;
emdp->in_cnt = 0;
emdp->out_cnt = 0;
flushactions(emdp);
savescreen(); /* in case we're logging the session */
logclose();
if (emdp->emwindow != NULL) {
if (!line25on(emdp))
pr25(0, nosessionstr);
status_info();
/* prettywind(TRUE);
results in cleared area when color is on */
if (keydp == NULL || emdp->emwindow == keydp->emwindow) {
/* fix menu to reflect status */
if (setmsession(emdp) || setmenuconn(emdp))
DrawMenuBar();
}
if (emdp->disposeonclose) {
/* kill window when closed */
queryclosewind(emdp);
}
}
}
tcpmst_run()
{
}
/* call wr_usr after getting the context */
tcpwr_usr(buf, len, urg)
unsigned char *buf;
int len;
int urg;
{
struct winds * oemdp;
oemdp = emdp;
getcontext(tcpemdp);
wr_usr(buf, len, urg);
if (emdp == oemdp)
emdp->modflg = modflg;
/* needs to be updated even if no context change so screen_service can
pick up the changes */
else
getcontext(oemdp);
}
/* call opn_usr after getting the context */
tcpopn_usr()
{
struct winds * oemdp;
oemdp = emdp;
getcontext(tcpemdp);
opn_usr();
getcontext(oemdp);
}
/* call cls_usr after getting the context */
tcpcls_usr()
{
struct winds * oemdp;
tcpemdp->closeflag = TRUE;
mtevent = TRUE;
}
/* make a new connection, do user dialog to configure it, and connect */
newconn()
{
if (makeconn())
return(-1);
opensettings();
getconfig(); /* do first, namewindow response may override */
releaseconfig(); /* release handles, which we don't want to use */
if (namewindow()) {
closesettings();
killconn();
return(-1);
}
emdp->newconf = TRUE;
/* it's a new, unopened file even if "Untitled" unchanged */
setappfilename();
if (makewind()) {
closesettings();
killconn();
return(-1);
}
emdp->resfid = 0;
setwindvols(emdp); /* set default directories */
closesettings();
emdp->keyxhead = NULL; /* don't inherit key resources */
restore25();
addwindmenu(emdp->emwindow);
openconn(emdp);
return(0);
}
/* make a new connection structure, initialize vt100 */
makeconn()
{
struct winds * otwp;
struct timer * otimer;
if (conncount >= MAXWIND)
return(-1);
if (connavailable) {
/* emdp is the only connection block lying around,
no window, no connection */
connavailable = FALSE;
emedit(emdp, TRUE);
/* save things from the old structure */
otimer = emdp->token_tm;
memzero(emdp, sizeof(struct winds));
/* zero out the new structure */
emdp->token_tm = otimer;
}
else {
if (!memtest((long) sizeof(struct winds), "to make session")) {
return(-1);
}
otwp = emdp;
savecontext(emdp);
emdp = NewPtr((Size) (sizeof(struct winds)));
if (emdp == NULL) {
emdp = otwp;
return(-1);
}
memzero(emdp, sizeof(struct winds));
/* zero out the new structure */
setcontext(emdp);
if ((emdp->token_tm = tm_alloc()) == NULL) {
DisposPtr(emdp);
getcontext(otwp);
return(-1);
}
}
emdp->emwindow = (WindowPtr) NULL;
emdp->iconwindow = (WindowPtr) NULL;
emdp->savefid = 0;
emdp->gotoy = -1;
emdp->cursorwait = TRUE;
ibmmode(FALSE);
emdp->putchar = nullputchar;
emdp->putflush = nullputflush;
conns[conncount] = emdp;
conncount++;
return(0);
}
/* destroy the most recent attempt to make a connection structure */
killconn()
{
--conncount;
conns[conncount] = NULL;
if (keydp != NULL) {
DisposPtr(emdp);
setcontext(keydp);
}
else {
setcontext(conns[0]);
}
}
/* standard close bottleneck call */
closeconn(twp)
struct winds * twp;
{
if (twp->connopen) {
getcontext(twp);
if (!hostclosemacro(twp->closemacro))
/* if there's no close macro, go ahead and close it up */
docloseconn();
}
}
/* REALLY do a close on the emdp connection */
docloseconn()
{
if (!emdp->connopen) {
return();
}
if (emdp->conntype == CONN_MACTCP) {
mactcp_close();
}
#ifdef DUALTCP
else if (emdp->conntype == CONN_CUTCP) {
tcp_close();
emdp->ucb.u_state = CLOSING;
emdp->ucb.u_rstate = BLOCK;
}
#endif
else if (emdp->conntype == CONN_SERD) {
windmenumark(emdp, noMark); /* clear any marks */
closeserport(emdp);
cls_usr(); /* WARNING: twp may disappear, emdp may change! */
}
}
/* remove a connection from the table, we have no connection */
releaseconn(twp)
struct winds * twp;
{
register short count = 0;
for (count = 0; count < conncount; count ++) {
if (twp == conns[count])
break;
}
if (count == conncount)
/* no such connection exists */
return(-1);
/* we found a match, release resources associated with it */
if (twp->conntype == CONN_MACTCP) {
if (mactcpopen) {
tcp_release(twp);
tcpmemoryreclaim(twp);
}
}
#ifdef DUALTCP
else if (twp->conntype == CONN_CUTCP) {
if (cutcpopen) {
/* TODO should we close down Cornell TCP completely to
allow MacTCP to run? */
/* tcpemdp = NULL; TODO this is improper! */
;
}
}
#endif
else if (twp->conntype == CONN_SERD) {
closeserport(twp);
}
if (conncount > 1) {
/* kill it */
ascii_free(twp); /* release any ASCII emulator memory */
ibm_free(twp); /* release any IBM emulator memory */
tm_clear(twp->token_tm);
tm_free(twp->token_tm);
DisposPtr(twp);
/* now shift down the other conns in the table */
for ( count++ ; count < conncount; count++) {
conns[count - 1] = conns[count];
}
/* set the context to the first one */
if (twp == emdp ) {
/* the current context has been devastated */
emdp = NULL;
getcontext(conns[0]); /* set context to the first one in the table */
}
if (twp == keydp) {
/* if the context was the one on top--very likely--
it exists no longer... */
keydp = NULL;
keywindow = NULL;
}
}
else {
/* leave one emdp struct around so
only 1 conn struct w/ no window exists */
if (quitonclose)
/* user wants close when no windows/sessions exist */
cu_exit(0);
connavailable = TRUE;
setcontext(emdp);
keydp = NULL;
keywindow = NULL;
emedit(emdp, TRUE);
showcursor(); /* make sure cursor drawn */
/* TODO windows need to be reset and should the config be reset? */
}
--conncount;
conns[conncount] = NULL;
}
/* open a connection for a connection/window structure
must be in emdp context (using getcontext() or makeconn() )
*/
openconn(twp)
struct winds * twp;
{
unsigned sock;
#ifdef ARPFORHOST
if (!at_arp(fhost.u.addr))
return(-2);
#endif
if (twp->connopen)
return;
#ifdef MACTCP
if (twp->conntype == CONN_CUTCP) {
/* force it */
twp->conntype = CONN_MACTCP;
}
#endif
if (twp->emwindow) {
/* fix the window and menu */
windmenumark(twp, noMark); /* clear any marks */
restore25();
}
if (twp->conntype == CONN_MACTCP
|| twp->conntype == CONN_CUTCP) {
telnetreset(twp->termtype);
}
if (twp->conntype == CONN_MACTCP
|| macipopen && twp->conntype == CONN_CUTCP) {
/* coerce MacTCP configuration if Cornell already started */
extern int mactcp_put();
extern int mactcp_ex();
twp->conntype = CONN_MACTCP;
twp->putchar = mactcp_put;
twp->putflush = mactcp_ex;
sock = tn_sock();
if (twp->fhost.u.addr == -1L
|| twp->fhost.u.addr == 0L) {
/* avoid opening sessions to broadcast address, can
induce Cornell AT-GW to produce telnet storms... */
error("Can't open Telnet session to the broadcast address; please reconfigure the session address");
}
else {
pr25(0, hostwait);
mactcp_open(&twp->fhost.u.addr, twp->fhost.port, sock);
}
}
#ifdef DUALTCP
else if (twp->conntype == CONN_CUTCP) {
extern int tc_put();
extern int tcp_ex();
if (tcpemdp == NULL) {
/* add gateway address slot */
tcpmenu();
}
else {
if (tcpemdp->connopen) {
error("Only one Cornell TCP session can be used at a time");
return(-1);
}
}
pr25(0, hostwait);
twp->putchar = tc_put;
twp->putflush = tcp_ex;
tcpemdp = twp;
if (!cutcpopen) {
if (opensettings())
error("Can't open 'Comet Default' document");
tcp_init(0, tcpopn_usr, tcpwr_usr, tcpmst_run,
tcpcls_usr, tcptmo_usr, tcppr_dot, tcpbfr);
cutcpopen = TRUE;
if (! (*rnet->n_subnet)()) {
if (get_subnet()) {
/* ignore lack of gateway, assume local net */
;
}
else {
closesettings();
return(-1);
}
}
closesettings();
}
sock = tn_sock();
tcp_open(&twp->fhost.u.addr, twp->fhost.port, sock);
}
#endif
else if (twp->conntype == CONN_SERD) {
extern int serputchar();
extern int serputflush();
twp->putchar = serputchar;
twp->putflush = serputflush;
termreset(); /* clear the old screen */
gettermtype();
setcontext(emdp);
setibm_keymode(twp->ibm_keymode);
/* get controls now, whereas Telnet must wait until negotiations cease */
if (openserport()) {
pr25(0, nosessionstr);
return(-1);
}
opn_usr();
emdp->tndata = TRUE; /* guarantee controls come up */
hostconncomplete(emdp->connmacro);
}
return(0);
}
#define DLACCEPT 2000
#define DLACYES 1
#define DLACNO 2
int tftp_direction;
tntftp(host, file, dir)
in_name host;
char *file;
unsigned dir;
{
char buffer[100];
char c;
short item;
DialogPtr dptr;
GrafPtr oldport;
tftp_direction = dir;
if (tftpask == TFNO) {
mac_setdownvol();
if (dir == PUT) {
/* save the text window if necessary */
textupedit(file);
}
return(TRUE);
}
else if (tftpask == TFYES) {
#ifdef BACKTFTPREJECT
if (chkbackground())
/* if asking on & we're in the background, reject the request */
return(FALSE);
#endif
if (host == emdp->fhost.u.addr) {
ctop(file);
HLock(emdp->hhostname);
ParamText(*emdp->hhostname, dir == PUT ? "\Pread" : "\Pwrite", file, "\P");
HUnlock(emdp->hhostname);
ptoc(file);
}
else {
sprintf(buffer, "%a", host);
ctop(buffer);
ctop(file);
ParamText(buffer, dir == PUT ? "\Pread" : "\Pwrite", file, "\P");
ptoc(file);
}
/* do dialog to determine if user will accept */
GetPort(&oldport);
emwdeactivate();
SetDAFont(systemFont);
if ( ( dptr =
GetNewDialog(DLACCEPT, (Ptr) NULL, (WindowPtr) -1) ) == NULL )
return(FALSE);
centerwind(dptr);
SetPort(dptr);
SetCursor(&arrow); /* guarantee cursor is not blank */
itemhighlight(dptr, 1);
modaldialog = TRUE;
while (TRUE) {
#ifdef MACTCP
ModalDialog( (ProcPtr) NULL, &item);
#else
extern Boolean alfilter();
ModalDialog( (ProcPtr) alfilter, &item);
#endif
switch (item) {
case DLACYES: {
DisposDialog(dptr);
SetPort(oldport);
modaldialog = FALSE;
mac_setdownvol(); /* fix the directory for multiple sessions */
if (dir == PUT)
textupedit(file);
return(TRUE);
}
case DLACNO: {
DisposDialog(dptr);
SetPort(oldport);
modaldialog = FALSE;
return(FALSE);
}
}
}
}
}
/* function called when file transfer is done. */
#define ALFTOK 2001
#define ALFTFAIL 2002
char transok[] = "File transferred OK\r";
char transfail[] = "File transfer FAILED\r";
tntfdn(success)
int success;
{
extern char macfile[]; /* for tftp Macintosh file name translation */
if (success) {
if (tftp_direction == GET) {
textdownedit(&macfile[0]);
}
}
else {
fillwindow(COPYWINDOW, transfail, (long) strlen(transfail), systemFont, 12, 0L);
}
}
itemhighlight(dlog, item)
DialogPtr dlog;
int item;
{
short itemtype;
Handle itemhand;
Rect itemrect;
GetDItem(dlog, (short) item, &itemtype, &itemhand, &itemrect);
PenSize(3, 3);
InsetRect(&itemrect, -4, -4);
FrameRoundRect(&itemrect, 16, 16);
}
/* check to see if we have enough memory */
char * memstr = "Not enough memory ";
long memtest(amount, usererr)
long amount;
char * usererr;
{
long free;
char errstr[120];
char * errp;
if ( (free = FreeMem()) < amount + 15000) {
strcpy(&errstr[0], memstr);
if (usererr != NULL)
strncat(&errstr[strlen(memstr)], usererr, 80);
prerr25(&errstr[0]);
return(0);
}
else
return(free);
}
#ifdef MACTCP
/* define stubs for uncalled functions */
tcptmo_usr()
{
}
tcpbfr()
{
}
tcppr_dot()
{
}
datayield()
{
}
#else
tcptmo_usr()
{
error("Cannot reach host");
tcpemdp->closeflag = TRUE;
mtevent = TRUE;
}
tcpbfr()
{
if (tcpemdp->ucb.u_tcpfull) {
tcpemdp->ucb.u_tcpfull = 0;
}
}
tcppr_dot()
{
}
datayield()
{
if (rnet->n_demux->ev_flg) {
/* input q needs service */
tkrun = rnet->n_demux;
tk_yield();
}
}
#endif
/* change controls & menus to reflect terminal we are emulating */
ibmmode(flag)
int flag;
{
extern int ibmproc_token();
extern int ibmsendchar();
extern int ibmsendstr();
extern int proc_token();
extern int asciisendchar();
extern int asciisendstr();
emdp->ibm_mode = flag;
/* select the token processor for handling user input */
if (emdp->ibm_mode) {
emdp->dotoken = ibmproc_token;
emdp->sendchar = ibmsendchar;
emdp->sendstr = ibmsendstr;
/* TODO we need to reset the color map if it wasn't configured ... */
}
else {
emdp->dotoken = proc_token;
emdp->sendchar = asciisendchar;
emdp->sendstr = asciisendstr;
}
}
/* set up the controls and key resources for the emulator type
TODO could be more efficient if already set...
*/
setibm_keymode(flag)
int flag;
{
/* fix controls */
reopenconfig(emdp);
if (emwindow != NULL) {
killcontrols(emwindow);
controlinit(emwindow, flag ? IBMRES : ASCRES);
/* do menu stuff */
if (emdp == keydp) {
if (keymenus(emdp))
DrawMenuBar();
}
}
/* fix the key resources */
keyxrelease();
if (!emdp->newconf)
keyxinit();
closeconfig(emdp);
}
#define MAXCLOSERS 30
static int (*closers[MAXCLOSERS])();
static int nclosers = 0;
exit_hook(func)
int (*func)();
{
if (nclosers < MAXCLOSERS)
closers[++nclosers] = func;
else
error("out of exit_hooks");
}
cu_exit(arg)
int arg;
{
int count;
for(count = nclosers; count; count--)
(*closers[count])();
exit(arg);
}
/* reset output context; most routines rely on the global emdp to
point to the current output window. Several per-window variables
are maintained also as globals to reduce overhead in the emulators
and avoid modifying old code (zap esp.) to use emdp.
It is crucial that the globals be maintained properly!
*/
getcontext(conp)
struct winds * conp;
{
if (conp == emdp) {
/* save some time */
if (emwindow) {
/* guarantee at a minimum that port is set right */
SetPort(emwindow);
}
return;
}
savecontext(emdp);
/* save the old global context before the change */
setcontext(conp);
}
/* set the globals from a winds struct; set them all, since otherwise
there might be a failure to save stuff during Telnet negotiations */
setcontext(conp)
register struct winds * conp;
{
if (conp == NULL)
return;
if (conp->emwindow) {
emwindow = conp->emwindow;
SetPort(emwindow); /* guarantee port is set right */
}
else
emwindow = NULL;
emdp = conp; /* set the major league window structure * globals */
thefont = conp->thefont; /* default font */
startarr = conp->startarr; /* dsdraw -> array of ptrs to scanline starts */
screenbytes = conp->screenbytes; /* width of screen in bytes */
screenrem = conp->screenrem; /* screenbytes - std screen */
fontwidth = conp->fontwidth;
xpos = conp->xpos;
ypos = conp->ypos; /* current x, y position */
modflg = conp->modflg; /* line modified bit array */
clrflg = conp->clrflg; /* line cleared bit array */
/* H19 vars */
mode = conp->mode; /* interpretation mode of emulator */
charp = conp->charp; /* ASCII -> cursor location in charr */
attrib = conp->attrib; /* normal/reverse mode for copy drawing */
wrap_around = conp->wrap_around; /* normal/reverse mode for copy drawing */
inserton = conp->inserton; /* insert mode */
linelength = conp->linelength; /* width of row */
lastcol = conp->lastcol; /* linelength - 1 */
/* vt100; preceeding are h19 vars also */
vtmode = conp->vtmode; /* new mode holder for vt100 */
argp = conp->argp; /* -> current argument */
/* variables important to the 3270 interpreter */
cmdstate = conp->cmdstate; /* state of the emulator */
scr_map = conp->scr_map; /* 3270 screen map */
smap_end = conp->smap_end; /* end of map */
current_attr = conp->current_attr; /* pointer to most recent attribute */
cursor_ptr = conp->cursor_ptr; /* current cursor position in screen map */
firstp = conp->firstp; /* ptr to first data byte processed for set_map */
}
/*
restore output context: save the globals which may have been modified for the
next time around with this window
*/
savecontext(conp)
register struct winds * conp;
{
if (conp == NULL)
return;
conp->xpos = xpos;
conp->ypos = ypos; /* BIGG current x, y position */
conp->modflg = modflg; /* BIGG line modified bit array */
conp->clrflg = clrflg; /* BIGG line cleared bit array */
/* h19 */
conp->mode = mode; /* BIGG interpretation mode of emulator */
conp->inserton = inserton; /* BIGG insert mode */
conp->attrib = attrib; /* BIGG normal/reverse mode for copy drawing */
conp->wrap_around = wrap_around; /* BIGG normal/reverse mode for copy drawing */
conp->charp = charp; /* BIGG ASCII -> cursor location in charr */
conp->linelength = linelength; /* BIGG width of row */
conp->lastcol = lastcol; /* BIGG linelength - 1 */
/* vt100 */
conp->vtmode = vtmode; /* BIGG new mode holder for vt100 */
conp->argp = argp; /* BIGG -> current argument */
/* 3270 */
conp->cmdstate = cmdstate; /* BIGG state of the emulator */
conp->scr_map = scr_map; /* BIGG 3270 screen map */
conp->smap_end = smap_end; /* BIGG end of map */
conp->current_attr = current_attr; /* BIGG pointer to most recent attribute */
conp->cursor_ptr = cursor_ptr; /* BIGG current cursor position in screen map */
conp->firstp = firstp; /* BIGG ptr to first data byte processed for set_map */
}
/* We check instead to see if any data has arrived and upcall if so,
and try to send things waiting on the queue */
short inio_service;
io_service()
{
struct winds ** conp = conns;
struct winds * conend = &conp[conncount];
register struct winds * twp;
int serialtime;
if (inio_service)
return;
inio_service = TRUE;
if (tickserial && cticks >= tickserial)
serialtime = TRUE;
else
serialtime = FALSE;
/* go through window list to see who needs service */
#ifdef TFTPSERVE
if (tfsdata || tftpdata)
/* MacTCP tftp service */
tftp_upcall();
#endif
if (mtevent) {
mtevent = FALSE; /* reset immediately after test: set asynchronously */
}
else if (serialtime) {
tickserial = cticks + serialwait;
}
else {
/* nothing happening, try to save time */
inio_service = FALSE;
return;
}
while (conp < conend) {
twp = *conp++;
if (twp == NULL)
continue;
#ifdef MAKEHYCCONN
if (twp->hycconnwait == TRUE) {
/* if the API has requested an open, do it */
/* use macro ? */
twp->hycconnwait = 1;
if (makeconn()) {
killconn();
continue;
}
getconfig();
emdp->resfid = appresfid;
emdp->resvol = appvol;
emdp->resdir = appdir;
keyxinit();
makewind();
openconn(emdp);
continue;
}
#endif
if (twp->conntype == CONN_MACTCP) {
/* has no new data... */
if (! (twp->data_rcvd || twp->closeflag || twp->send_wait))
continue;
/* reset output context */
getcontext(twp);
if (twp->data_rcvd) {
tcp_upcall();
twp->modflg = modflg;
/* update; could use savecontext() but not only modflg needed */
}
#ifdef ASYNCOPEN
if (!modaldialog && twp->openflag) {
opn_usr();
}
#endif
if (!modaldialog && twp->closeflag) {
/* don't EVER do this in the background, cls_usr may dialog */
mactcp_wrapup(); /* WARNING: twp may disappear, emdp may change! */
}
if (twp->send_wait) {
/* a packet is waiting for buffer; try to send again */
mactcp_ex();
}
else if (twp->fillcount && (twp->fillcount == twp->waitcount)) {
/* SHOULD NEVER REACH THIS POINT! symptom of
MacTCP async "let's waste some variables" behavior */
prerr25("send_wait clobbered");
mactcp_ex();
}
continue;
}
#ifdef DUALTCP
else if (twp->conntype == CONN_CUTCP) {
if (!modaldialog && twp->closeflag) {
/* close the session */
/* don't EVER do this in the background, cls_usr may dialog */
twp->closeflag = FALSE;
getcontext(twp);
windmenumark(twp, noMark); /* clear any marks */
cls_usr(); /* WARNING: twp may disappear, emdp may change! */
}
continue;
}
#endif
else if (twp->conntype == CONN_SERD && serialtime) {
/* check for serial data */
getcontext(twp);
serial_service();
twp->modflg = modflg;
continue;
}
else if (twp->conntype == CONN_COMMMGR) {
/* check for comm mgr data */
;
continue;
}
}
inio_service = FALSE;
}
nullputchar()
{
}
nullputflush()
{
}
/* called in the main user task to serve I/O while in dialog
or other modal situation */
bkrd_service()
{
struct winds * oemdp;
GrafPtr oport;
oemdp = emdp;
GetPort(&oport);
token_service(); /* user output--handle actions waiting on the queue */
io_service(); /* for merged MacTCP/CUTCP */
#ifdef DUALTCP
tk_yield(); /* task yield for Cornell TCP */
#endif
screen_service(); /* update screen */
if (emdp != oemdp)
/* restore the old context for all the callers out there */
getcontext(oemdp);
if (oport)
SetPort(oport); /* might not be emwindow */
}
/* turn the tftp server on
*/
#define OFF 0
#define ON 1
tfs_on()
{
extern short tfstate;
if (!tftpopen) {
if (emdp->conntype == CONN_MACTCP) {
if (mtcp_tfsinit(tntftp, tntfdn))
return(FALSE);
tftpopen = TRUE;
}
#ifdef DUALTCP
else if (emdp->conntype == CONN_CUTCP) {
if (tfsinit(tntftp, tntfdn))
return(FALSE);
tftpopen = TRUE;
}
#endif
}
tfstate = ON;
return(TRUE);
}
/* turn the tftp server off
*/
tfs_off()
{
extern short tfstate;
tfstate = OFF;
}
/* set the name in the appfile struct used for document naming control */
setappfilename()
{
register char * chp;
register char * endp;
register char * destp;
/* copy the name into the appfile struct from hhostname;
hhostname is a Pascal string */
chp = *emdp->hhostname;
endp = chp + **emdp->hhostname + 1;
destp = &emdp->appfile.fName;
while (chp < endp) {
*destp++ = *chp++;
}
}
istcptype()
{
if (emdp->conntype == CONN_SERD || emdp->conntype == CONN_COMMMGR)
return(FALSE);
else
return(TRUE);
}
/* added for compatibility with MPW */
SwapMMUMode(chararg)
Byte * chararg;
{
#asm
move.l 8(a6),a0 ; -> byte arg
move.b (a0),d0 ; d0 = arg
dc.w $a05d ; _SwapMMUMode
move.b d0,(a0) ; return current mode in arg
#endasm
}
#ifndef DUALTCP
tcp_close()
{
}
DialogPtr nnrdptr;
shownnr()
{
}
hidennr()
{
}
#endif
invalidconn(twp)
struct winds * twp;
{
register short count = 0;
for (count = 0; count < conncount; count++) {
if (twp == conns[count])
return(0);
}
/* no such connection exists */
return(-1);
}